#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include "sy_core.h"


#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <cmath>

#define MinX 0
#define MaxX 500
#define MinY 0
#define MaxY 500
#define WINW 500
#define WINH 500


using namespace MAP;

int map[N+1][N+1]; //0 NOT 2 Black 1 white
POS* border=new POS;
POS_D put_POSS_BLACK[257]; int put_NUM_BLACK;
POS_D put_POSS_WHITE[257]; int put_NUM_WHITE;
int NOW_BNUM = 2,NOW_WNUM = 2;
int dir[6],tc,X = 0,Y = 0,cnt = 0,who,style,color;
int Rec[63][2];

int LBx = -230,LBy = 10,RBx = 500,RBy = 10,TLx = 10,TLy = 480,TRx = 250,TRy = 480;

bool legal,start,starting;

void DrawCircle(float cx, float cy, float r, int Num) { 

	float theta = 2 * 3.1415926 / float(Num); 
	float c = cosf(theta);
	float s = sinf(theta);
	float t;

	float x = r; 
	float y = 0; 

	glPolygonMode(GL_FRONT,GL_LINE);
	glLineWidth(5);
	glBegin(GL_POLYGON); 
	for(int ii = 0; ii < Num; ii++) 
	{ 
		glVertex2f(x + cx, y + cy); 
		t = x;
		x = c * x - s * y;
		y = s * t + c * y;
	}
	glEnd(); 

	x = --r; y = 0;
	glPolygonMode(GL_FRONT,GL_FILL);
	glBegin(GL_POLYGON); 
	for(int ii = 0; ii < Num; ii++) 
	{ 
		glVertex2f(x + cx, y + cy); 
		t = x;
		x = c * x - s * y;
		y = s * t + c * y;
	}
	glEnd(); 
}

void Update() {

	Can_drop_black(map,put_POSS_BLACK,border,put_NUM_BLACK);
	Can_drop_white(map,put_POSS_WHITE,border,put_NUM_WHITE);

	memset(map_black_dir,0,sizeof(map_black_dir));
	memset(map_white_dir,0,sizeof(map_white_dir));

	for (int i=1; i<=put_NUM_BLACK; i++)
	{
		map_black_dir[put_POSS_BLACK[i].x][put_POSS_BLACK[i].y].dir=put_POSS_BLACK[i].dir;
		map_black_dir[put_POSS_BLACK[i].x][put_POSS_BLACK[i].y].col=2;
	}
	for (int i=1; i<=put_NUM_WHITE; i++)
	{
		map_white_dir[put_POSS_WHITE[i].x][put_POSS_WHITE[i].y].dir=put_POSS_WHITE[i].dir;
		map_white_dir[put_POSS_WHITE[i].x][put_POSS_WHITE[i].y].col=1;
	}
	Draw(map,X,Y);
	glutPostRedisplay();
}

void ShowString(const char *str,int x,int y) {

	glColor3f(0.0,0.0,0.0);
	glRasterPos2i(x,y);
	int len = strlen(str);
	for (int i = 0; i < len; i++)
		glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,*(str + i));	

}

void Draw() {

	glClear(GL_COLOR_BUFFER_BIT);

	glColor3f(0.0,0.5,0.3);
	glPolygonMode(GL_FRONT,GL_FILL);
	glBegin(GL_POLYGON);
	int l = (Y - 1) * 60 + 5,r = l + 60,b = (N - X) * 60 + 5,t = b + 60;
	glVertex2d(l,b);
	glVertex2d(l,t);
	glVertex2d(r,t);
	glVertex2d(r,b);
	glEnd();
	//last
	glLineWidth(1);
	glLineStipple(1,0x0F0F);
	glEnable(GL_LINE_STIPPLE);
	glColor3f(0.0,1.0,0.4);
	glBegin(GL_LINES);
	for (int x = 0; x <= 8; x++)
	{
		glVertex2d(5 + x * 60,0);
		glVertex2d(5 + x * 60,MaxY);
	}
	for (int y = 0; y <= 8; y++)
	{
		glVertex2d(0,5 + y * 60);
		glVertex2d(MaxX,5 + y * 60);
	}
	//draw grid
	glEnd();
	glDisable(GL_LINE_STIPPLE);

	if (start)
	{
		for (int x = 1; x <= 8; x++)
			for (int y = 1,i = 8; y <= 8; y++,i--)
				if (map[i][x])
				{
					int c = map[i][x];
					if (color == 2) c = 3 - c;
					if (c == 1) glColor3f(1.0,1.0,1.0);
					else glColor3f(0.0,0.0,0.0);
					DrawCircle(25 * ((x << 1) - 1) + x * 10,25 * ((y << 1) - 1) + y * 10,25,64);
				}
	}
	else
	{
		const char Name[50] = "SyotH -- v0.1";
		const char First[50] = "Lady First!";
		const char YourColor[50] = "Choose Your Color:";
		ShowString(Name,200,470);
		int x1 = LBx,y1 = LBy,x2 = x1 + 230,y2 = y1 + 230;
		glColor3f(0.2,0.2,0.2);
		glBegin(GL_POLYGON);
		glVertex2d(x1,y1);
		glVertex2d(x2,y1);
		glVertex2d(x2,y2);
		glVertex2d(x1,y2);
		glEnd();
		if (color == 1) glColor3d(0,0,0); else glColor3d(1,1,1);
		DrawCircle(x1 + 145,y1 + 145,25,64);
		DrawCircle(x1 + 85,y1 + 85,25,64);
		if (color == 1) glColor3d(1,1,1); else glColor3d(0,0,0);
		DrawCircle(x1 + 85,y1 + 145,25,64);
		DrawCircle(x1 + 145,y1 + 85,25,64);

		x1 = RBx,y1 = RBy,x2 = x1 + 230,y2 = y1 + 230;
		glColor3f(0.2,0.2,0.2);
		glBegin(GL_POLYGON);
		glVertex2d(x1,y1);
		glVertex2d(x2,y1);
		glVertex2d(x2,y2);
		glVertex2d(x1,y2);
		glEnd();
		if (color == 1) glColor3d(1,1,1); else glColor3d(0,0,0);
		DrawCircle(x1 + 145,y1 + 145,25,64);
		DrawCircle(x1 + 85,y1 + 85,25,64);
		if (color == 1) glColor3d(0,0,0); else glColor3d(1,1,1);
		DrawCircle(x1 + 85,y1 + 145,25,64);
		DrawCircle(x1 + 145,y1 + 85,25,64);

		x1 = TLx,y1 = TLy,x2 = TLx + 230,y2 = TLy + 210;
		if (who == 2) glColor3f(0.2,0.2,0.2); else glColor3f(0.3,0.2,0.2);
		glBegin(GL_POLYGON);
		glVertex2d(x1,y1);
		glVertex2d(x2,y1);
		glVertex2d(x2,y2);
		glVertex2d(x1,y2);
		glEnd();
		ShowString(First,x1 + 80,y1 + 120);

		x1 = TRx,y1 = TRy,x2 = TRx + 230,y2 = TRy + 210;
		glColor3f(0.2,0.2,0.2);
		glBegin(GL_POLYGON);
		glVertex2d(x1,y1);
		glVertex2d(x2,y1);
		glVertex2d(x2,y2);
		glVertex2d(x1,y2);
		glEnd();
		if (color == 2) glColor3d(0,0,0); else glColor3d(1,1,1);
		DrawCircle(x1 + 115,y1 + 100,25,64);
		ShowString(YourColor,x1 + 30,y1 + 160);
	}
	glFlush();
	glutSwapBuffers();
}

void Turn() {

	if (start)
	{
		if (who == 1)
		{
			if (!put_NUM_WHITE) {who = 2; return;}
			if (map_white_dir[X][Y].col==1)
			{
				int tmp = Drop_white(X,Y,map,map_white_dir[X][Y].dir,Rec);
				NOW_BNUM -= tmp;
				NOW_WNUM += tmp + 1;
				Expand(X,Y,border,map);
				Del(X,Y,border);
				Update();

				FILE *output = fopen("yoursteps.out","a");
				fprintf(output,"%d %d\n",X,Y);
				fclose(output);
				who = 2;
				legal = 0;
			}
		}
		else if (who == 2)
		{
			if (!put_NUM_WHITE && !put_NUM_BLACK) 
			{
				who = 0;
				if (NOW_BNUM > NOW_WNUM) printf("AI WIN!\n");
				else if (NOW_BNUM < NOW_WNUM) printf("YOU are the WINNER!\n");
				else printf("Tie! - - \n");
				printf("Score: %d\n",NOW_BNUM - NOW_WNUM);
				return;
			}
			if (!put_NUM_BLACK) {who = 1; legal = 1; return;}
			AI::AI_next(map,border,NOW_BNUM,NOW_WNUM,X,Y);//thinking...
			int tmp = Drop_black(X,Y,map,map_black_dir[X][Y].dir,Rec);
			NOW_WNUM -= tmp;
			NOW_BNUM += tmp + 1;
			Expand(X,Y,border,map);
			Del(X,Y,border);
			printf("Turn %d: \"Syoth\" dropped at (%d,%d)\no:%.2d x:%.2d\n",++cnt,X,Y,NOW_WNUM,NOW_BNUM);
			Update();
			legal = 1;
			who = 1;
		}
	}
	else
	{
		bool conti = 0;
		if (starting)
		{
			if (LBx >= -230) {LBx--; conti = 1;}
			if (RBx <= 500) {RBx++; conti = 1;}
			if (TLy <= 500) {TLy++; conti = 1;}
			if (TRy <= 500) {TRy++; conti = 1;}
			if (!conti) 
			{
				if (who == 1) legal = 1; else legal = 0;
				Start(map,border,put_NUM_BLACK,put_NUM_WHITE,style);
				Update();
				start = 1;
				glutPostRedisplay();
			}
		}
		else
		{
			if (LBx < 10) {LBx++; conti = 1;}
			if (RBx > 250) {RBx--; conti = 1;}
			if (TLy > 250) {TLy--; conti = 1;}
			if (TRy > 250) {TRy--; conti = 1;}
		}
		if (conti) glutPostRedisplay();
	}
}

void Drop(int button,int state,int x,int y) {

	if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
	{
		if (start)
		{
			if (legal)
			{
				int vx = MinX + x,vy = MaxY - y;
				if (vx <= 480 && vy <= 480 && vx % 60 > 10 && vy % 60 > 10)
				{
					int posi = 8 - vy / 60,posj = vx / 60 + 1;
					printf("%d %d\n",posi,posj);
					X = posi; Y = posj;
				}
			}
		}
		else
		{
			y = MaxY - y;
			if (10 <= x && x <= 240 &&  250 <= y && y <= 480) 
			{
				who = who == 1 ? 2 : 1;
				glutPostRedisplay();
			}
			else if (250 <= x && x <= 480 && 250 <= y && y <= 480)
			{
				color = color == 1 ? 2 : 1;
				glutPostRedisplay();
			}
			else if (10 <= x && x <= 240 && 10 <= y && y <= 240) {style = 1; starting = 1;}
			else if (250 <= x && x <= 480 && 10 <= y && y <= 240) {style = 2; starting = 1;}
		}
	}
}

void Adjust(int width,int height) {

	glViewport(0,height - MaxY,MaxX,MaxY);
}

void Graphinit(int argc,char **argv) {

	glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
	glutInitWindowPosition(100,0);
	glutInitWindowSize(WINW,WINH);
	glutCreateWindow("Syoth v0.1");

	glClearColor(0.3333,0.4196,0.1843,0.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(MinX,MaxX,MinY,MaxY,-1.0,1.0);
	glEnable(GL_LINE_SMOOTH);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
}

int main(int argc,char **argv) {


	FILE *output = fopen("yoursteps.out","w");
	fclose(output);
	srand(time(0));
	memset(dir,0,sizeof(dir));
	memset(map,0,sizeof(map));

	AI::Initdp();
	Graphinit(argc,argv);
	who = 2; color = 1;
	border -> next = NULL;
	start = starting = style = 0;
	Update();
	glutMouseFunc(Drop);
	glutDisplayFunc(Draw);
	glutIdleFunc(Turn);
	glutReshapeFunc(Adjust);
	glutMainLoop();
	return 0;
}

